package com.d2rabbit.exception.aspect;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.d2rabbit.exception.annotation.Check;
import com.d2rabbit.exception.annotation.ParameterCheck;
import com.d2rabbit.exception.base.BaseBean;
import com.d2rabbit.exception.exception.ParameterCheckException;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Map;

/**
 * 参数校验切面
 * */
@Aspect
@Component
public class ParameterCheckAop {

	@Pointcut(value = "@annotation(com.d2rabbit.exception.annotation.ParameterCheck)")
	public void checkAspect() {

	}
	@Around(value = "checkAspect()")
	public Object aroundCheckException(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
		MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
		Method method = signature.getMethod();
		ParameterCheck parameterCheck = method.getAnnotation(ParameterCheck.class);
		Class<? extends BaseBean> clazz = parameterCheck.bean();
		Annotation[][] parameterAnnotations = method.getParameterAnnotations();
		if (parameterAnnotations.length == 0) {
			return proceedingJoinPoint.proceed();
		}
		//获取参数值
		Object[] paramValues = proceedingJoinPoint.getArgs();
		Map<String, Object> map = null;
//            获取参数值
		for (Object paramValue : paramValues){
			if(paramValue instanceof BaseBean){
				map = BeanUtil.beanToMap(paramValues[0]);
				break;
			}
		}
		if (map == null) {
			return proceedingJoinPoint.proceed();
		}
		Field[] fields = clazz.getDeclaredFields();
		// 对含有 check注解的参数进行对应的校验
		for (Field field : fields) {
			if (field.isAnnotationPresent(Check.class)) {
				Check check = field.getAnnotation(Check.class);
				//出现不符合规则的参数，统一抛出ParameterCheckException异常
				if (ObjectUtil.isEmpty((map.get(field.getName())))) {
					throw new ParameterCheckException(check.msg());
				}
			}
		}
	    return proceedingJoinPoint.proceed();
	}
}
